package sceneObjects;

import org.eclipse.swt.graphics.ImageData;

import utils.ColorRGB;
import utils.Point3D;
import main.Intersection;
import main.Parseable;
import main.Parser;
import main.RayTracer;

public abstract class abstractSceneObject implements sceneObject, Parseable {

    private enum SurfaceType {
	FLAT, CHECKERS, TEXTURE
    };

    private ImageData textureImg;
    private String surfaceType;
    private SurfaceType type;
    private ColorRGB kDiffuse;
    private ColorRGB kSpecular;
    private ColorRGB kAmbient;
    private double nShininess;
    private double checkersSize;
    private ColorRGB checkersDiffuse1;
    private ColorRGB checkersDiffuse2;
    private String textureFilename;
    private double kReflectance;

    public Point3D getParameterization(Intersection intersect) {
	return new Point3D(0, 0, 0);
    }

    public ColorRGB getKD(Intersection intersect) {

	if (type == SurfaceType.TEXTURE || type == SurfaceType.CHECKERS) {
	    Point3D texParam = getParameterization(intersect);
	    double u = texParam.getX();
	    double v = texParam.getY();

	    if (type == SurfaceType.TEXTURE) {
		return new ColorRGB(textureImg.getPixel((int) (textureImg.width * u), (int) (textureImg.height * v)));
	    } else { // checkers
		boolean x = (((int) (u / (checkersSize)) % 2) == 1);
		boolean y = (((int) (v / (checkersSize)) % 2) == 0);
		return (x ^ y == false) ? checkersDiffuse1 : checkersDiffuse2;
	    }
	} else {
	    return new ColorRGB(kDiffuse);
	}
    }

    public ColorRGB getKA() {
	return new ColorRGB(kAmbient);
    }

    public ColorRGB getKS() {
	return new ColorRGB(kSpecular);
    }

    public double getKR() {
	return kReflectance;
    }

    public double getNS() {
	return nShininess;
    }

    public abstractSceneObject() {
	type = SurfaceType.FLAT;
	kDiffuse = new ColorRGB(0.7, 0.7, 0.7);
	kSpecular = new ColorRGB(1, 1, 1);
	kAmbient = new ColorRGB(0.1, 0.1, 0.1);
	nShininess = 100;
	checkersSize = 0.1;
	checkersDiffuse1 = new ColorRGB(1, 1, 1);
	checkersDiffuse2 = new ColorRGB(0.2, 0.2, 0.2);
	textureFilename = null;
	kReflectance = 0;
	surfaceType = "flat";
    }

    @Override
    public boolean setParameter(String name, String[] args) {
	if (name.equals("mtl-type")) {
	    if (args.length != 1) {
		System.out.println("bad parameters");
		return false;
	    }
	    surfaceType = args[0];
	    return true;
	} else if (name.equals("mtl-diffuse")) {
	    if (args.length != 3) {
		System.out.println("bad parameters");
		return false;
	    }
	    kDiffuse = new ColorRGB(Parser.stringArrToDoubleArr(args));
	    return true;
	} else if (name.equals("mtl-specular")) {
	    if (args.length != 3) {
		System.out.println("bad parameters");
		return false;
	    }
	    kSpecular = new ColorRGB(Parser.stringArrToDoubleArr(args));
	    return true;
	} else if (name.equals("mtl-ambient")) {
	    if (args.length != 3) {
		System.out.println("bad parameters");
		return false;
	    }
	    kAmbient = new ColorRGB(Parser.stringArrToDoubleArr(args));
	    return true;
	} else if (name.equals("mtl-shininess")) {
	    if (args.length != 1) {
		System.out.println("bad parameters");
		return false;
	    }
	    nShininess = Double.parseDouble(args[0]);
	    return true;
	} else if (name.equals("checkers-size")) {
	    if (args.length != 1) {
		System.out.println("bad parameters");
		return false;
	    }
	    checkersSize = Double.parseDouble(args[0]);
	    return true;
	} else if (name.equals("checkers-diffuse1")) {
	    if (args.length != 3) {
		System.out.println("bad parameters");
		return false;
	    }
	    checkersDiffuse1 = new ColorRGB(Parser.stringArrToDoubleArr(args));
	    return true;
	} else if (name.equals("checkers-diffuse2")) {
	    if (args.length != 3) {
		System.out.println("bad parameters");
		return false;
	    }
	    checkersDiffuse2 = new ColorRGB(Parser.stringArrToDoubleArr(args));
	    return true;
	} else if (name.equals("texture")) {
	    if (args.length != 1) {
		System.out.println("bad parameters");
		return false;
	    }
	    textureFilename = args[0];
	    return true;
	} else if (name.equals("reflectance")) {
	    if (args.length != 1) {
		System.out.println("bad parameters");
		return false;
	    }
	    kReflectance = Double.parseDouble(args[0]);
	    return true;
	}
	return false;
    }

    @Override
    public boolean finalizeObject() {
	// Check that a legal surface type was given
	if (surfaceType.equals("flat")) {
	    type = SurfaceType.FLAT;
	} else if (surfaceType.equals("checkers")) {
	    type = SurfaceType.CHECKERS;
	} else if (surfaceType.equals("texture")) {
	    type = SurfaceType.TEXTURE;
	} else {
	    System.out.println("Illegel surface type");
	    return false;
	}

	// Check that the img file is legal
	if (textureFilename != null) {
	    try {
		textureImg = new ImageData((RayTracer.getPathName() + "/" + textureFilename));
	    } catch (Exception e) {
		System.out.println(e.getMessage());
		return false;
	    }
	}

	if (type == SurfaceType.CHECKERS && checkersSize <= 0) {
	    System.out.println("checkersize must be bigger than zero");
	    return false;
	}

	return true;
    }

    public boolean isCamera() {
	return false;
    }

    public boolean isLight() {
	return false;
    }

}
